/*
 * Copyright 2005 PayPal, Inc. All Rights Reserved.
 */

using System;
using System.Text;
using System.Runtime.InteropServices;
using System.IO;

namespace com.paypal.sdk.util
{
	/// <summary>
	/// Crypto 32 API abstract class.
	/// </summary>
	public abstract class Crypto32API
	{
		/// <summary>
		/// MY_STORE
		/// </summary>
		public const string MY_STORE = "MY";
		

		/// <summary>
		/// ROOT_STORE 
		/// </summary>
		public const string ROOT_STORE = "ROOT";
		

		/// <summary>
		/// CRYPT_USER_KEYSET
		/// </summary>
		public const uint CRYPT_USER_KEYSET	= 0x00001000;
		
		
		/// <summary>
		/// CERT_FIND_SUBJECT_STR
		/// </summary>
		public const uint CERT_FIND_SUBJECT_STR	= 0x00080007;
		

		/// <summary>
		/// CERT_KEY_PROV_INFO_PROP_ID
		/// </summary>
		public const uint CERT_KEY_PROV_INFO_PROP_ID = 0x00000002;
		
		
		/// <summary>
		/// CERT_STORE_ADD_NEW
		/// </summary>
		public const uint CERT_STORE_ADD_NEW = 0x00000002;
		
		
		/// <summary>
		///  CERT_SYSTEM_STORE_CURRENT_USER
		/// </summary>
		public const uint CERT_SYSTEM_STORE_CURRENT_USER = 0x00010000;
		

		/// <summary>
		/// CERT_STORE_READONLY_FLAG
		/// </summary>
		public const uint CERT_STORE_READONLY_FLAG = 0x00008000;
		

		/// <summary>
		/// CERT_STORE_OPEN_EXISTING_FLAG
		/// </summary>
		public const uint CERT_STORE_OPEN_EXISTING_FLAG	= 0x00004000;
		

		/// <summary>
		/// CERT_SYSTEM_STORE_CURRENT_SERVICE
		/// </summary>
		public const uint CERT_SYSTEM_STORE_CURRENT_SERVICE = 0x00000003;

		
		/// <summary>
		/// CERT_SYSTEM_STORE_LOCAL_MACHINE
		/// </summary>
		public const uint CERT_SYSTEM_STORE_LOCAL_MACHINE = 0x2 << 16;
		
		
		/// <summary>
		/// CERT_SYSTEM_STORE_MYSUSER_MACHINE
		/// </summary>
		public const uint CERT_SYSTEM_STORE_MYSUSER_MACHINE = 0x1 << 16;


		/// <summary>
		/// CERT_STORE_PROV_LM_SYSTEM_STORE
		/// </summary>
		public const int CERT_STORE_PROV_LM_SYSTEM_STORE = 10;

		/// <summary>
		/// PFXImportCertStore
		/// </summary>
		[DllImport("crypt32.dll", CharSet=CharSet.Auto, SetLastError=true)]	
		public static extern IntPtr PFXImportCertStore(ref CryptoDataBlob pPfx, [MarshalAs(UnmanagedType.LPWStr)] string szPassword, uint dwFlags);

		
		/// <summary>
		/// PFXIsPFXBlob
		/// </summary>
		[DllImport("crypt32.dll", CharSet=CharSet.Auto, SetLastError=true)]	
		public static extern bool PFXIsPFXBlob(ref CryptoDataBlob pPfx);

		
		/// <summary>
		/// CertOpenSystemStore
		/// </summary>
		[DllImport("crypt32.dll", CharSet=CharSet.Auto, SetLastError=true)]
		public static extern IntPtr CertOpenSystemStore(IntPtr hCryptProv, string storename);
		
		
		/// <summary>
		/// CertOpenStore
		/// </summary>
		[DllImport("crypt32.dll", CharSet=CharSet.Auto, SetLastError=true)]
		public static extern IntPtr CertOpenStore(IntPtr lpszStoreProvider, uint dwMsgAndCertEncodingType, IntPtr hCryptProv, uint dwFlags, string pvPara);

		
		/// <summary>
		/// CertCloseStore
		/// </summary>
		[DllImport("crypt32.dll", CharSet=CharSet.Auto, SetLastError=true)]
		public static extern bool CertCloseStore(IntPtr hCertStore, uint dwFlags);

		
		/// <summary>
		/// CertEnumCertificatesInStore
		/// </summary>
		[DllImport("crypt32.dll", CharSet=CharSet.Auto, SetLastError=true)]
		public static extern IntPtr CertEnumCertificatesInStore(IntPtr hCertStore, IntPtr pPrevCertContext);

		
		/// <summary>
		/// CertAddCertificateContextToStore
		/// </summary>
		[DllImport("crypt32.dll", CharSet=CharSet.Auto, SetLastError=true)]
		public static extern bool CertAddCertificateContextToStore(IntPtr hCertStore, IntPtr pCrlContext, uint dwAddDisposition, IntPtr ppStoreContext);

		
		/// <summary>
		/// CertFreeCertificateContext
		/// </summary>
		[DllImport("crypt32.dll", CharSet=CharSet.Auto, SetLastError=true)]
		public static extern bool CertFreeCertificateContext(IntPtr hCertStore);	
	
		
		/// <summary>
		/// CertFindCertificateInStore
		/// </summary>
		[DllImport("crypt32.dll", SetLastError=true)]
		public static extern IntPtr CertFindCertificateInStore(IntPtr hCertStore, uint dwCertEncodingType, uint dwFindFlags, uint dwFindType, String pvFindPara, IntPtr pPrevCertCntxt);

		
		/// <summary>
		/// CryptoDataBlob
		/// </summary>
		[StructLayout(LayoutKind.Sequential)]
		public struct CryptoDataBlob
		{
			/// <summary>
			/// cbData
			/// </summary>
			public int cbData;

			/// <summary>
			///pbData
			/// </summary>
			public IntPtr pbData;
		}
    
		
		/// <summary>
		/// ReadPFXCertificateFile
		/// </summary>
		public static CryptoDataBlob ReadPFXCertificateFile(string pfxFileName)
		{
			CryptoDataBlob pfxBlob = new CryptoDataBlob();
			byte[] pfxData = null;
			
			if (!File.Exists(pfxFileName))
			{
				throw(new Exception(string.Format("File '{0}' not found.", pfxFileName)));
			}
			else
			{
				Stream stream = new FileStream(pfxFileName, FileMode.Open);
				int dataLength = (int)stream.Length;
				pfxData = new byte[dataLength];
				stream.Seek(0, SeekOrigin.Begin);
				stream.Read(pfxData, 0, dataLength);
				stream.Close();

				pfxBlob = CopyByteToCryptoBlob(pfxData);
			}

			return pfxBlob;
		}

		
		/// <summary>
		/// CopyByteToCryptoBlob
		/// </summary>
		public static CryptoDataBlob CopyByteToCryptoBlob(byte[] pfxData)
		{
			CryptoDataBlob pfxBlob = new CryptoDataBlob();

			if(pfxData == null || pfxData.Length == 0)
			{				
				throw(new Exception("Unable to read pfx file."));
			}
			else
			{
				pfxBlob.cbData = pfxData.Length;
				pfxBlob.pbData = Marshal.AllocHGlobal(pfxData.Length);
				Marshal.Copy(pfxData, 0, pfxBlob.pbData, pfxData.Length);
			}

			return pfxBlob;
		}

		
		/// <summary>
		/// IsValidPFXCertificate
		/// </summary>
		public static bool IsValidPFXCertificate(CryptoDataBlob pfxBlob)
		{
			return PFXIsPFXBlob(ref pfxBlob);
		}
	} //Crypto32API
} // util namespace